#!/bin/bash
#
# Bash-Version >= 1.14.0
#
# WICHTIG: Diese Datei muss *IX-Zeilenenden haben, also jede Zeile muss
#          mit LF abgeschlossen sein, nicht mit CR+LF, sonst meldet Bash
#          Syntaxfehler!
#
# Dieses Script gehoert in ein Verzeichnis, das in PATH erwaehnt wird,
# z.B. /usr/bin
# Alle Dateien, die die Endungen $cpp_def, $cpp_imp und $cpp_mod
# haben, werden mit dem Praeprozessor bearbeitet und ins Zielverzeichnis
# geschrieben.
#
# In der Funktion setup() koennen/muessen folgende Dinge festgelegt
# werden:
# o $def_macros: Der vollstaendige Pfad der Datei 'portab.m2h'
# o $cpp_* : Die Endungen der mit Praeprozessorkommandos versehenen M2-Dateien
# o $m2_*  : Die Endungen der reinen M2-Dateien
#

setup ()
{
    # Vollstaendiger Pfad der Makrodatei 'PORTAB.M2H':
    def_macros=/e/m2/lib/include/portab.m2h

    # Die Extensionen der praeprozessierten Ergebnismodule werden anhand
    # des angegebenen Compilers bestimmt:
    if [ $compiler = HM2 ]
    then
        m2_def=d
        m2_imp=m
        m2_mod=m
    elif [ $compiler = MM2 ]
    then
        m2_def=d
        m2_imp=i
        m2_mod=m
    else
        m2_def=def
        m2_imp=mod
        m2_mod=mod
    fi

    # Extensionen der Module mit Praeprozessorkommandos:
    cpp_def=dpp
    cpp_imp=ipp
    cpp_mod=mpp
}

################################################
# AB HIER NICHTS NDERN
################################################

# Name dieses Scripts ohne den Pfad (basename):
script=${0##*[\\/]}

usage_try="Probiere \`$script -h' fr weitere Informationen."

usage_help="\
Aufruf: $script [OPTIONEN] compiler destdir

 -d dir         Alle Dateien im Verzeichnis <dir>
 -s dir         Alle Dateien in allen Unterverzeichnissen von <dir>
 -f file        Nur Datei <file>
 -m macros      <macros> statt des Default-PORTAB.M2H benutzen
 -q             Keine Meldungen auer denen des Prprozessors
 -h             Dieser Text

M2-Dateien mit Prprozessorkommandos werden in reine M2-Dateien
umgewandelt.
Fr <compiler> kann eine der folgenden Konstanten angegeben werden:
LPRM2, SPCM2, TDIM2, MM2, HM2.
Die Optionen -s, -d und -f schlieen sich gegenseitig aus. Ohne eine
dieser Optionen werden alle Dateien im aktuellen Verzeichnis bearbeitet.
Optionen drfen nicht gruppiert werden und Argumente mssen von der
Option durch ein Leerzeichen getrennt sein."


# Eine Datei durch den Praeprozessor schicken

pp_file ()
{
    # Nur Dateiname ohne Pfad (basename)
    f=${1##*[\\/]}

    # Extension der Zieldatei setzen
    case $f in
        *.$cpp_def) dst=${f%.$cpp_def}.$m2_def ;;
        *.$cpp_imp) dst=${f%.$cpp_imp}.$m2_imp ;;
        *.$cpp_mod) dst=${f%.$cpp_mod}.$m2_mod ;;

        # Andere Dateien nicht bearbeiten:
        *) return 0 ;;
    esac

    # Datei durch den Praeprozessor schicken:
    if [ $quiet = no ]
    then
        echo -n "$script: $1 --> $destdir/$dst..."
    fi

    cpp -undef -P -D$compiler -imacros $macros $1 | x2d1 > $destdir/$dst

    if [ $quiet = no ]
    then
        echo "done."
    fi
}

pp_dir ()
{
    for file in $1/*
    do
        pp_file $file
    done
}

pp_subdirs ()
{
    # Bei der allerersten Dateinamensexpansion im Wurzelverzeichnis einer
    # GEMDOS-Partition nach dem Start der Shell wird die physikalisch erste
    # Datei unterschlagen (wahrscheinlich wegen fehlendem . und ..), deswegen
    # beim ersten Mal im Leerlauf.
    # Beispiel: Nach dem Start der Shell als ersten Befehl eingeben:
    #
    #           echo /c/*
    #
    #           Wenn man den Befehl zum zweiten Mal eingibt, wird eine Datei
    #           mehr aufgelistet. Wichtig ist, dass fuer die Eingabe des
    #           Befehls die Dateinamenvervollstaendigung (mit Tab) nicht
    #           verwendet wird.
    for dir in $1/*; do :; done

    for dir in $1/*
    do
        if [ -d $dir ]
        then
            pp_dir $dir
        fi
    done
}

opt_arg_test ()
{
    if [ $# -ne 3 ]
    then
        echo "$0: Option $1: Argument fehlt"
        exit 1
    elif [ $2 = file -a ! -f $3 ]
    then
        echo "$0: Option $1: \`$3' ist keine regulre Datei"
        exit 1
    elif [ $2 = dir  -a ! -d $3 ]
    then
        echo "$0: Option $1: \`$3' ist kein Verzeichnis"
        exit 1
    fi
}

###############
# Hier beginnts
###############

# Optionen analysieren

opt_d=no
opt_s=no
opt_f=no
opt_m=no
quiet=no

while [ $# -ne 0 ]
do
    case $1 in
        -d) opt_d=yes
            source=$2
            opt_arg_test d dir $2
            shift 2
            ;;
        -s) opt_s=yes
            source=$2
            opt_arg_test s dir $2
            shift 2
            ;;
        -f) opt_f=yes
            source=$2
            opt_arg_test f file $2
            shift 2
            ;;
        -m) opt_m=yes
            macros=$2
            opt_arg_test m file $2
            shift 2
            ;;
        -q) quiet=yes
            shift
            ;;
        -h) # Nur Hilfe ausgeben
            echo "$usage_help"
            exit 0
            ;;
        -*) # Bei falscher Option Script sofort abbrechen
            echo "$0: Unbekannte Option -- ${1#-}"
            echo "$usage_try"
            exit 1
            ;;
         *) # Ab hier keine Optionen mehr, Schleife beenden
            break
            ;;
    esac
done

# Moegliche Fehler beim Aufruf abfangen

if [ $# -ne 2 ]
then
    echo "$0: Zuwenig oder zuviel Parameter"
    echo "$usage_try"
    exit 1
fi

compiler=$1

case $compiler in
    HM2|MM2|LPRM2|SPCM2|TDIM2 ) ;;
    *)  echo "$0: Compiler \`$compiler' wird nicht untersttzt"
        echo "$usage_try"
        exit 2
        ;;
esac

# Quell- und Zielverzeichnis ohne evtl. abschliessenden Pfadtrenner
source=${source%[\\/]}
destdir=${2%[\\/]}

if [ ! -d $destdir ]
then
    echo "$0: Zielverzeichnis $destdir existiert nicht"
    exit 1
fi

# Die konfigurierbaren Variablen setzen
setup

if [ $opt_m = no ]
then
    macros=$def_macros
fi

if [ $opt_f = yes ]
then
    pp_file $source
elif [ $opt_d = yes ]
then
    pp_dir $source
elif [ $opt_s = yes ]
then
    pp_subdirs $source
else
    pp_dir ${PWD%[\\/]}
fi
